import { MiddlewareConsumer, Module, RequestMethod } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { RedisModule } from '@nestjs-modules/ioredis';
import { UserModule } from './modules/user/user.module';
import { VideoModule } from './modules/video/video.module';
import { AppService } from './app.service';
import { AppController } from './app.controller';
import { JwtModule } from '@nestjs/jwt';
import { JwtStrategy } from './common/middleware/jwt.strategy';
import { APP_GUARD } from '@nestjs/core';
import { JwtAuthGuard } from './common/guards/jwtAuth.guard';
import { PassportModule } from '@nestjs/passport';
import { EmailModule } from './modules/email/email.module';
import { FollowModule } from './modules/follow/follow.module';
import { QiniuModule } from './modules/qiniu/qiniu.module';
import { CronModule } from './cron/cron.module';
import { LikeModule } from './modules/like/like.module';
import { ScheduleModule } from '@nestjs/schedule';
import { FavoriteModule } from './modules/favorite/favorite.module';
import { VideoHistoryModule } from './modules/video-history/video-history.module';
import { CommentModule } from './modules/comment/comment.module';
import { UserAdminModule } from './modules/user-admin/user-admin.module';
import { RolesModule } from './modules/roles/roles.module';
import { MenuModule } from './modules/menu/menu.module';
import { DeptModule } from './modules/dept/dept.module';
import { DictModule } from './modules/dict/dict.module';
import { SysVisitLog } from './entities/sys-visit-log.entity';
import { VisitLogMiddleware } from './common/middleware/visit-log.middleware';
import { StatisticsModule } from './modules/statistics/statistics.module';
import { RecommendationModule } from './modules/recommendation/recommendation.module';
import { VideoCategoryModule } from './modules/video-category/video-category.module';
import { SearchModule } from './modules/search/search.module';

@Module({
  imports: [
    TypeOrmModule.forFeature([SysVisitLog]),
    ConfigModule.forRoot({
      isGlobal: true,
    }),
    JwtModule.registerAsync({
      global: true,
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => {
        return {
          secret: 'hqh030201',
          signOptions: {
            expiresIn: '24h',
          },
        };
      },
    }),
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'hqh030201',
      database: 'video_demo_database',
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true,
      autoLoadEntities: true,
    }),
    RedisModule.forRoot({
      type: 'single',
      options: {
        host: '47.119.181.254',
        port: 6379,
        password: 'hqh030201',
        // 添加重连和错误处理配置
        retryStrategy(times) {
          // 重试策略，最多等待2秒重试
          return Math.min(times * 100, 2000);
        },
        // 添加超时设置
        connectTimeout: 10000,
        // 启用自动重连
        reconnectOnError(err) {
          const targetError = 'READONLY';
          if (err.message.includes(targetError)) {
            // 只有在特定错误时重连
            return true;
          }
          return false;
        },
        // 启用保持连接
        keepAlive: 10000,
        // 启用离线队列
        enableOfflineQueue: true,
        // 最大重试次数
        maxRetriesPerRequest: 3,
      },
    }),
    ScheduleModule.forRoot(),
    PassportModule,
    UserModule,
    VideoModule,
    EmailModule,
    FollowModule,
    QiniuModule,
    CronModule,
    LikeModule,
    FavoriteModule,
    VideoHistoryModule,
    CommentModule,
    UserAdminModule,
    RolesModule,
    MenuModule,
    DeptModule,
    DictModule,
    StatisticsModule,
    RecommendationModule,
    VideoCategoryModule,
    SearchModule,
  ],
  controllers: [AppController],
  providers: [
    AppService,
    // jwt鉴权守卫
    JwtStrategy,
    {
      provide: APP_GUARD,
      useClass: JwtAuthGuard,
    },
  ],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(VisitLogMiddleware)
      .forRoutes({ path: '*', method: RequestMethod.ALL });
  }
}
